

namespace Crux.Core.LangChain.OpenAI;
/// <summary>
/// 
/// </summary>
public class OpenChatCompletionService(OpenAIOption option) : IChatCompletionService
{
    private readonly OpenAIOption _option = option
            ?? throw new ArgumentNullException(nameof(option));
    /// <summary>
    /// 
    /// </summary>
    /// <param name="messages"></param>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    public async Task<ChatHistoryMessage> CompleteChatAsync(IEnumerable<ChatHistoryMessage> messages, CancellationToken cancellationToken = default)
    {
        var client = GetChatClient();

        using var source = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);

        source.CancelAfter(60_000);

        var chatMessages = messages.Select(m =>
        {
            ChatMessage message = m.Role.Label.ToLower() switch
            {
                "system" => ChatMessage.CreateSystemMessage(m.Content),
                "assistant" => ChatMessage.CreateAssistantMessage(m.Content),
                "user" => ChatMessage.CreateUserMessage(m.Content),
                "tool" => ChatMessage.CreateToolMessage(m.Content),
                _ => ChatMessage.CreateUserMessage(m.Content)
            };

            return message;
        });

        ClientResult<ChatCompletion> completion = await client.CompleteChatAsync(
            chatMessages,
            cancellationToken: source.Token).ConfigureAwait(false);

        return new ChatHistoryMessage
        {
            Role = completion.Value.Role switch
            {
                ChatMessageRole.Assistant => Role.Assistant,
                ChatMessageRole.Tool => Role.Tool,
                ChatMessageRole.System => Role.System,
                ChatMessageRole.User => Role.User,
                _ => Role.User
            },
            Content = completion.Value.Content?.FirstOrDefault()?.Text ?? string.Empty
        };
    }
    private ChatClient GetChatClient()
    {
        var option = new OpenAIClientOptions
        {
            Endpoint = _option.Endpoint
        };
        var credential = new ApiKeyCredential(_option.ApiKey);

        var client = new ChatClient(
            model: _option.Model,
            credential,
            option);
        return client;
    }

}